const util = require('util');
const cc = require('./conCtl');
const js = require('./jsCtl');
const got = require('got');

const { wechat } = require('./config.json');


const tryErr = (title, body) => {
    if (body.errcode && body.errcode != 0) {//微信返回值错误
        let __err = { id: -3, str: '' };
        __err.str = `(${title}) error on wechat errcode:${body.errcode}, errmsg:${body.errmsg}`;
        js.throwObj(__err.str);
        return;
    }
    return true;
};

//获取随机字符串
const createNonceStr = function () {
    let ret = Math.random().toString(36).substr(2, 15);

    cc.log("create nonce string: " + ret);
    return ret;
};

//获取时间戳（秒）
const createTimestamp = function () {
    let ret = parseInt(new Date().getTime() / 1000) + '';

    cc.log("create time stamp: " + ret);
    return ret;
};

//排序算法
const raw = function (args) {
    var keys = Object.keys(args);
    keys = keys.sort();
    var newArgs = {};
    keys.forEach(function (key) {
        newArgs[key.toLowerCase()] = args[key];
    });

    var string = '';
    for (var k in newArgs) {
        string += '&' + k + '=' + newArgs[k];
    }
    string = string.substr(1);
    return string;
};

/**
* @synopsis 签名算法
*
* @param jsapi_ticket 用于签名的 jsapi_ticket
* @param url 用于签名的 url ，注意必须动态获取，不能 hardcode
*
* @returns
*/
const sign = function (jsapi_ticket, url) {
    let ret = {
        jsapi_ticket: jsapi_ticket,
        nonceStr: createNonceStr(),
        timestamp: createTimestamp(),
        url: url
    };
    let tmp = raw(ret);
    ret.signature = crypto.createHash("sha1").update(tmp).digest("hex");


    cc.log("client url signature completed", tmp, ret);

    ret.appId = wechat.appId;
    return ret;
};

const access_token = {
    token: "",
    last_time: 0,//token 最后更新的 process.uptime() 时间戳(精确到秒)
    updateAccessToken: async () => {
        return new Promise(async (r, e) => {
            try {
                let url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${wechat.appId}&secret=${wechat.appSecret}`;
                let body = await got(url).json();
                cc.log("start access_token request wechat <url>, and return <result> ", { url: url, result: body });
                tryErr('access_token', body);
                r(body);
            } catch (err) {
                e(err);
            }
        });
    },
    get: async () => {
        return new Promise(async (r, e) => {
            try {
                let now_time = process.uptime();//用秒来计算
                cc.log("access_token begin......local overtime.",
                    {
                        now: now_time,
                        overtime: access_token.last_time,
                        over: (now_time - access_token.last_time)
                    });
                if (now_time - access_token.last_time > -100) {//提前100秒更新
                    let body = await access_token.updateAccessToken();
                    access_token.token = body.access_token;
                    access_token.last_time = now_time + body.expires_in;

                    cc.log("get wechat <access_token> done ", { access_token: access_token.token });

                    r(access_token.token);
                }
                else {
                    cc.log("get local <access_token> done", { access_token: access_token.token });
                    r(access_token.token);
                }
            } catch (err) {
                e(err);
            }
        });

    }
};


/* 登录相关 ********************************************************/
const getUserInfoByCode = async (wechat_code) => {
    return new Promise(async r => {
        //通过 code 取得微信OAuth2.0鉴权所需的 access_token，这个 token 和 wechatSDK 中用的不是同一个（详见微信开放平台文档）
        //访问微信并获取用户登录信息
        let url = `https://api.weixin.qq.com/sns/oauth2/access_token?appid=${wechat.appId}&secret=${wechat.appSecret}&code=${wechat_code}&grant_type=authorization_code`;
        cc.log(url);
        let body = await got(url).json();
        cc.log("start get wechat user access_token for <url>, and return <result> ", { url: url, result: body });
        tryErr('get wechat user access_token', body);
        // body.openid,        //用户的唯一标识
        // body.access_token,  //网页授权接口调用凭证,注意：此 access_token 与基础支持的 access_token 不同
        // body.scope,         //返回国家地区语言版本，zh_CN 简体，zh_TW 繁体，en 英语
        // body.expires_in,    //access_token 接口调用凭证超时时间，单位（秒）
        // body.refresh_token; //用户刷新 access_token

        //获取用户信息
        let url2 = `https://api.weixin.qq.com/sns/userinfo?access_token=${body.access_token}&openid=${body.openid}&lang=zh_CN`;
        let body2 = await got(url2).json();
        cc.log("start get wechat user info by <url>, and return <result> ", { url: url2, result: body2 });
        tryErr('get wechat user info', body2);

        body2.openid = body.openid;
        r(body2);
    });
};


const jsapi_ticket = {
    ticket: "",
    last_time: 0,//ticket 最后更新的 process.uptime() 时间戳(精确到秒)
    updateJsapiTicket: async (accessToken) => {
        return new Promise(async (r, e) => {
            try {
                let url = `https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${accessToken}&type=jsapi`;

                let body = await got(url).json();
                cc.log("start jsapi_ticket request wechat <url>, and return <result>", { url: url, result: body });
                tryErr('jsapi_ticket', body);
                r(body);
            } catch (err) {
                e(err);
            }
        });
    },
    get: () => {
        return new Promise(async (r, e) => {
            try {
                let now_time = process.uptime();//用秒来计算
                cc.log("jsapi_ticket begin......local overtime.",
                    {
                        now: now_time,
                        overtime: jsapi_ticket.last_time,
                        over: (now_time - jsapi_ticket.last_time)
                    });
                if (now_time - jsapi_ticket.last_time > -100) {//提前100秒更新
                    let token = await access_token.get();
                    let body = await jsapi_ticket.updateJsapiTicket(token);

                    jsapi_ticket.ticket = body.ticket;
                    jsapi_ticket.last_time = now_time + body.expires_in;

                    cc.log("get wechat <jsapi_ticket>", { jsapi_ticket: jsapi_ticket.ticket });

                    r(jsapi_ticket.ticket);
                }
                else {
                    cc.log("get local <jsapi_ticket>", { jsapi_ticket: jsapi_ticket.ticket });
                    r(jsapi_ticket.ticket);
                }
            } catch (err) {
                e(err);
            }
        });
    }

};
const get_jsapi_ticket = () => {
    return jsapi_ticket.get();
}



//发送微信订阅号消息
// template_id: 'U_09CvxUqgXtttWml92s2S4Xfym4Cs9fPt8arW19e6A',
// miniprogram: { appid: wechat.appId, pagepath: }
// url: wechat.base.baseurl + '/jiekuanxiangqing.html?id=' + orderid
const send_wechat_msg = async (openid, first, operate, amt, status, date, remark, template_id = '', miniprogram = {}, url = '') => {
    return new Promise(async r => {
        let token = await get_access_token();
        let data = {
            touser: openid,
            template_id,
            url,
            miniprogram,
            data: {
                first: { value: first, },
                OPERATE: { value: operate, },
                AMT: { value: amt, },
                STATUS: { value: status, },
                DATE: { value: date || ((new Date()).toLocaleDateString() + " " + (new Date()).toLocaleTimeString()), },
                remark: { value: remark, },
            }
        };

        let body = await got('https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=' + token, {
            method: "POST",
            headers: {
                "content-type": "application/json",
                "charset": "UTF-8",
                "Accept": "application/json",
                "Cache-Control": " no-cache",
                "Pragma": " no-cache",
            },
            json: data
        }).json();
        tryErr('发送微信消息', body);
        r();

    });
};
const queryString = require('querystring');
const crypto = require('crypto');

/**
 * 获取微信支付的签名
 * @param payParams
 */
const getSign = (signParams) => {
    // 按 key 值的ascll 排序
    var keys = Object.keys(signParams);
    keys = keys.sort();
    var newArgs = {};
    keys.forEach(function (val, key) {
        if (signParams[val]) {
            newArgs[val] = signParams[val];
        }
    })
    var string = queryString.stringify(newArgs) + '&key=' + wechat.pay.mch_key;
    // 生成签名
    return crypto.createHash('md5').update(queryString.unescape(string), 'utf8').digest("hex").toUpperCase();
}

module.exports = {
    sign,
    getUserInfoByCode,
    get_jsapi_ticket,
    send_wechat_msg,
    getSign,

};